using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AdminSG3L.Domain.Entities;
using AdminSG3L.Domain.Repositories;
using AdminSG3L.Applicaticn.ServicesInterface;
using AdminSG3L.Applicaticn.Commands;
using Serilog;
using AdminSG3L.Applicaticn.Dtos;

namespace AdminSG3L.Applicaticn.Services;

/// <summary>
/// 菜单服务实现，支持并发处理
/// </summary>
public class MenuService(IRepository<AppMenu> menuRepository) : IMenuService, IDisposable
{
    private readonly IRepository<AppMenu> _menuRepository = menuRepository;
    
    // 并发控制：菜单缓存
    private readonly ConcurrentDictionary<Guid, AppMenu> _menuCache = new();
    
    // 并发控制：读写锁
    private readonly ReaderWriterLockSlim _cacheLock = new(LockRecursionPolicy.SupportsRecursion);
    
    // 并发控制：信号量限制并发操作数量
    private readonly SemaphoreSlim _operationSemaphore = new(10, 10); // 最多10个并发操作

    #region 缓存管理方法

    /// <summary>
    /// 尝试从缓存获取菜单
    /// </summary>
    /// <param name="id">菜单ID</param>
    /// <param name="menu">输出的菜单对象</param>
    /// <returns>是否成功获取</returns>
    private bool TryGetFromCache(Guid id, out AppMenu? menu)
    {
        _cacheLock.EnterReadLock();
        try
        {
            return _menuCache.TryGetValue(id, out menu);
        }
        finally
        {
            _cacheLock.ExitReadLock();
        }
    }

    /// <summary>
    /// 添加菜单到缓存
    /// </summary>
    /// <param name="menu">菜单对象</param>
    private void AddToCache(AppMenu menu)
    {
        if (menu == null) return;
        
        _cacheLock.EnterWriteLock();
        try
        {
            _menuCache.AddOrUpdate(menu.Id, menu, (key, oldValue) => menu);
        }
        finally
        {
            _cacheLock.ExitWriteLock();
        }
    }

    /// <summary>
    /// 从缓存中移除菜单
    /// </summary>
    /// <param name="id">菜单ID</param>
    private void RemoveFromCache(Guid id)
    {
        _cacheLock.EnterWriteLock();
        try
        {
            _menuCache.TryRemove(id, out _);
        }
        finally
        {
            _cacheLock.ExitWriteLock();
        }
    }

    /// <summary>
    /// 清空缓存
    /// </summary>
    private void ClearCache()
    {
        _cacheLock.EnterWriteLock();
        try
        {
            _menuCache.Clear();
        }
        finally
        {
            _cacheLock.ExitWriteLock();
        }
    }

    #endregion

    #region 接口实现方法

    /// <summary>
    /// 根据ID获取菜单（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<AppMenu?>> GetByIdAsync(Guid id)
        => await GetByIdAsync(id, CancellationToken.None);

    /// <summary>
    /// 创建菜单（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<MenuDto>> CreateAsync(CreateMenuDto dto)
        => await CreateAsync(dto, CancellationToken.None);

    /// <summary>
    /// 批量创建菜单（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<IEnumerable<MenuDto>>> BatchCreateAsync(IEnumerable<CreateMenuDto> dtos)
        => await BatchCreateAsync(dtos, CancellationToken.None);

    #endregion

    /// <summary>
    /// 根据ID获取菜单（支持并发缓存）
    /// </summary>
    /// <param name="id">菜单ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>菜单实体</returns>
    public async Task<ApiResponse<AppMenu?>> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        if (id == Guid.Empty)
        {
            return ApiResponse<AppMenu?>.Fail("菜单ID无效");
        }

        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            // 尝试从缓存中获取
            if (TryGetFromCache(id, out var cachedMenu))
            {
                Log.Debug("从缓存获取菜单，Id={MenuId}", id);
                return ApiResponse<AppMenu?>.Success(cachedMenu);
            }

            // 缓存未命中，从数据库获取
            var menu = await _menuRepository.GetByIdAsync(id);
            if (menu == null)
            {
                return ApiResponse<AppMenu?>.Fail("菜单不存在");
            }

            // 添加到缓存
            AddToCache(menu);
            Log.Information("获取菜单成功并缓存，Id={MenuId}", id);
            return ApiResponse<AppMenu?>.Success(menu);
        }
        catch (OperationCanceledException)
        {
            Log.Warning("获取菜单操作被取消，Id={MenuId}", id);
            return ApiResponse<AppMenu?>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取菜单异常，Id={MenuId}", id);
            return ApiResponse<AppMenu?>.Fail($"获取菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 创建菜单（支持并发安全）
    /// </summary>
    /// <param name="dto">创建菜单DTO</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>创建结果</returns>
    public async Task<ApiResponse<MenuDto>> CreateAsync(CreateMenuDto dto, CancellationToken cancellationToken = default)
    {
        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var menu = AppMenu.Create(dto.MenuName, dto.MenuCode, dto.ParentId, null, null, dto.Icon, dto.Path, dto.Description);
            await _menuRepository.AddAsync(menu);
            
            // 添加到缓存
            AddToCache(menu);
            
            var result = new MenuDto(menu.Id, menu.MenuName, menu.MenuCode, menu.ParentId, menu.Icon, menu.Path, menu.Description);
            Log.Information("创建菜单成功，Id={MenuId}, Name={MenuName}", menu.Id, menu.MenuName);
            return ApiResponse<MenuDto>.Success(result);
        }
        catch (OperationCanceledException)
        {
            Log.Warning("创建菜单操作被取消，Name={MenuName}", dto.MenuName);
            return ApiResponse<MenuDto>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "创建菜单异常，Name={MenuName}", dto.MenuName);
            return ApiResponse<MenuDto>.Fail($"创建菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 批量创建菜单（支持并发处理）
    /// </summary>
    /// <param name="dtos">菜单DTO集合</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>创建结果</returns>
    public async Task<ApiResponse<IEnumerable<MenuDto>>> BatchCreateAsync(IEnumerable<CreateMenuDto> dtos, CancellationToken cancellationToken = default)
    {
        if (dtos == null || !dtos.Any())
        {
            return ApiResponse<IEnumerable<MenuDto>>.Fail("菜单数据不能为空");
        }

        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var menuList = dtos.ToList();
            var menus = new List<AppMenu>();
            
            // 并发创建菜单实体
            var createTasks = menuList.Select(dto => Task.Run(() => 
                AppMenu.Create(dto.MenuName, dto.MenuCode, dto.ParentId, null, null, dto.Icon, dto.Path, dto.Description),
                cancellationToken)).ToArray();
            
            menus.AddRange(await Task.WhenAll(createTasks));
            
            // 批量保存到数据库
            await _menuRepository.AddRangeAsync(menus);
            
            // 批量添加到缓存
            foreach (var menu in menus)
            {
                AddToCache(menu);
            }
            
            var result = menus.Select(menu => new MenuDto(menu.Id, menu.MenuName, menu.MenuCode, menu.ParentId, menu.Icon, menu.Path, menu.Description));
            Log.Information("批量创建菜单成功，数量={Count}", menus.Count);
            return ApiResponse<IEnumerable<MenuDto>>.Success(result);
        }
        catch (OperationCanceledException)
        {
            Log.Warning("批量创建菜单操作被取消");
            return ApiResponse<IEnumerable<MenuDto>>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "批量创建菜单异常");
            return ApiResponse<IEnumerable<MenuDto>>.Fail($"批量创建菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 更新菜单（支持并发安全）
    /// </summary>
    /// <param name="dto">更新菜单DTO</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>更新结果</returns>
    public async Task<ApiResponse<bool>> UpdateAsync(UpdateMenuDto dto, CancellationToken cancellationToken = default)
    {
        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var menu = await _menuRepository.GetByIdAsync(dto.Id);
            if (menu == null)
                return ApiResponse<bool>.Fail("菜单不存在");
                
            menu.Update(dto.MenuName, dto.MenuCode, dto.ParentId, dto.Icon, dto.Path, dto.Description);
            await _menuRepository.UpdateAsync(menu);
            
            // 更新缓存
            AddToCache(menu);
            
            Log.Information("更新菜单成功，Id={MenuId}", dto.Id);
            return ApiResponse<bool>.Success(true);
        }
        catch (OperationCanceledException)
        {
            Log.Warning("更新菜单操作被取消，Id={MenuId}", dto.Id);
            return ApiResponse<bool>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "更新菜单异常，Id={MenuId}", dto.Id);
            return ApiResponse<bool>.Fail($"更新菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 更新菜单（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<bool>> UpdateAsync(UpdateMenuDto dto)
        => await UpdateAsync(dto, CancellationToken.None);

    /// <summary>
    /// 删除菜单（支持并发安全）
    /// </summary>
    /// <param name="id">菜单ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>删除结果</returns>
    public async Task<ApiResponse<bool>> DeleteAsync(Guid id, CancellationToken cancellationToken = default)
    {
        if (id == Guid.Empty)
        {
            return ApiResponse<bool>.Fail("菜单ID无效");
        }

        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var menu = await _menuRepository.GetByIdAsync(id);
            if (menu == null)
            {
                return ApiResponse<bool>.Fail("菜单不存在");
            }

            // 检查是否已经被软删除
            if (menu.IsDeleted)
            {
                return ApiResponse<bool>.Fail("菜单已被删除");
            }

            // 调用实体的Delete方法（这会检查IsSystem属性）
            menu.Delete();
            menu.UpdateTime();
            await _menuRepository.UpdateAsync(menu);
            
            // 从缓存中移除
            RemoveFromCache(id);
            
            Log.Information("菜单软删除成功，Id={MenuId}", id);
            return ApiResponse<bool>.Success(true, "删除成功");
        }
        catch (OperationCanceledException)
        {
            Log.Warning("删除菜单操作被取消，Id={MenuId}", id);
            return ApiResponse<bool>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "删除菜单异常，Id={MenuId}", id);
            return ApiResponse<bool>.Fail($"删除菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 删除菜单（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<bool>> DeleteAsync(Guid id)
        => await DeleteAsync(id, CancellationToken.None);

    /// <summary>
    /// 批量删除菜单（支持并发处理）
    /// </summary>
    /// <param name="ids">菜单ID集合</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>删除结果</returns>
    public async Task<ApiResponse<int>> BatchDeleteAsync(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
    {
        if (ids == null || !ids.Any())
        {
            return ApiResponse<int>.Fail("ID集合不能为空");
        }

        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var idList = ids.ToList();
            var menus = (await _menuRepository.GetAllAsync()).Where(m => idList.Contains(m.Id) && !m.IsDeleted).ToList();
            
            if (menus.Count == 0)
            {
                return ApiResponse<int>.Fail("未找到要删除的菜单或菜单已被删除");
            }

            int deletedCount = 0;
            var failedMenus = new List<string>();

            // 逐个调用实体的Delete方法
            foreach (var menu in menus)
            {
                try
                {
                    menu.Delete(); // 这会检查IsSystem属性
                    menu.UpdateTime();
                    await _menuRepository.UpdateAsync(menu);
                    
                    // 从缓存中移除
                    RemoveFromCache(menu.Id);
                    deletedCount++;
                }
                catch (InvalidOperationException ex)
                {
                    // 记录无法删除的系统菜单
                    failedMenus.Add($"{menu.MenuName}: {ex.Message}");
                    Log.Warning("菜单删除被阻止，Id={MenuId}, 菜单名={MenuName}, 原因={Reason}", menu.Id, menu.MenuName, ex.Message);
                }
            }

            if (failedMenus.Any())
            {
                var message = $"批量删除完成，成功删除 {deletedCount} 个，失败 {failedMenus.Count} 个。失败原因：{string.Join("；", failedMenus)}";
                Log.Information("批量删除菜单部分成功，删除数量={DeletedCount}, 失败数量={FailedCount}", deletedCount, failedMenus.Count);
                return ApiResponse<int>.Success(deletedCount, message);
            }
            else
            {
                Log.Information("批量删除菜单成功，数量={Count}", deletedCount);
                return ApiResponse<int>.Success(deletedCount, "批量删除成功");
            }
        }
        catch (OperationCanceledException)
        {
            Log.Warning("批量删除菜单操作被取消");
            return ApiResponse<int>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "批量删除菜单异常");
            return ApiResponse<int>.Fail($"批量删除菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 批量删除菜单（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<int>> BatchDeleteAsync(IEnumerable<Guid> ids)
        => await BatchDeleteAsync(ids, CancellationToken.None);

    /// <summary>
    /// 获取所有菜单DTO（支持并发缓存）
    /// </summary>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>菜单DTO集合</returns>
    public async Task<ApiResponse<IEnumerable<MenuDto>>> GetAllDtoAsync(CancellationToken cancellationToken = default)
    {
        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var menus = await _menuRepository.GetAllAsync();
            
            // 并发转换为DTO
            var dtoTasks = menus.Select(menu => Task.Run(() => 
                new MenuDto(menu.Id, menu.MenuName, menu.MenuCode, menu.ParentId, menu.Icon, menu.Path, menu.Description),
                cancellationToken)).ToArray();
            
            var dtos = await Task.WhenAll(dtoTasks);
            
            // 批量添加到缓存
            foreach (var menu in menus)
            {
                AddToCache(menu);
            }
            
            Log.Information("获取所有菜单成功，数量={Count}", dtos.Length);
            return ApiResponse<IEnumerable<MenuDto>>.Success(dtos);
        }
        catch (OperationCanceledException)
        {
            Log.Warning("获取所有菜单操作被取消");
            return ApiResponse<IEnumerable<MenuDto>>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取所有菜单异常");
            return ApiResponse<IEnumerable<MenuDto>>.Fail($"获取所有菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 获取所有菜单DTO（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<IEnumerable<MenuDto>>> GetAllDtoAsync()
        => await GetAllDtoAsync(CancellationToken.None);

    /// <summary>
    /// 分页获取菜单DTO（支持并发处理）
    /// </summary>
    /// <param name="pageIndex">页索引</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>分页结果</returns>
    public async Task<ApiResponse<(IEnumerable<MenuDto> Menus, int TotalCount)>> GetPagedDtoAsync(
        int pageIndex, int pageSize, CancellationToken cancellationToken = default)
    {
        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            var all = await _menuRepository.GetAllAsync();
            var total = all.Count();
            
            // 并发分页处理
            var pagedMenus = all.Skip(pageIndex * pageSize).Take(pageSize).ToList();
            
            var dtoTasks = pagedMenus.Select(menu => Task.Run(() =>
                new MenuDto(menu.Id, menu.MenuName, menu.MenuCode, menu.ParentId, menu.Icon, menu.Path, menu.Description),
                cancellationToken)).ToArray();
            
            var page = await Task.WhenAll(dtoTasks);
            
            // 添加到缓存
            foreach (var menu in pagedMenus)
            {
                AddToCache(menu);
            }
            
            Log.Information("分页获取菜单成功，页={PageIndex}, 大小={PageSize}, 总数={Total}", pageIndex, pageSize, total);
            return ApiResponse<(IEnumerable<MenuDto>, int)>.Success((page, total));
        }
        catch (OperationCanceledException)
        {
            Log.Warning("分页获取菜单操作被取消");
            return ApiResponse<(IEnumerable<MenuDto>, int)>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "分页获取菜单异常");
            return ApiResponse<(IEnumerable<MenuDto>, int)>.Fail($"分页获取菜单异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 分页获取菜单DTO（接口兼容性方法）
    /// </summary>
    public async Task<ApiResponse<(IEnumerable<MenuDto> Menus, int TotalCount)>> GetPagedDtoAsync(int pageIndex, int pageSize)
        => await GetPagedDtoAsync(pageIndex, pageSize, CancellationToken.None);

    public async Task<ApiResponse<int>> GetCountAsync()
    {
        try
        {
            var count = await _menuRepository.CountAllAsync();
            return ApiResponse<int>.Success(count);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取菜单总数异常");
            return ApiResponse<int>.Fail($"获取菜单总数异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<MenuDto?>> FindOneAsync(Func<MenuDto, bool> predicate)
    {
        if (predicate == null)
        {
            return ApiResponse<MenuDto?>.Fail("查询条件不能为空");
        }
        try
        {
            var menus = await _menuRepository.GetAllAsync();
            var dtos = menus.Select(m => new MenuDto(m.Id, m.MenuName, m.MenuCode, m.ParentId, m.Icon, m.Path, m.Description));
            var result = dtos.FirstOrDefault(predicate);
            if (result == null)
            {
                return ApiResponse<MenuDto?>.Fail("未找到菜单");
            }
            else
            {
                return ApiResponse<MenuDto?>.Success(result);
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex, "条件查询单个菜单异常");
            return ApiResponse<MenuDto?>.Fail($"条件查询单个菜单异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<IEnumerable<MenuDto>>> FindManyAsync(Func<MenuDto, bool> predicate)
    {
        if (predicate == null)
        {
            return ApiResponse<IEnumerable<MenuDto>>.Fail("查询条件不能为空");
        }
        try
        {
            var menus = await _menuRepository.GetAllAsync();
            var dtos = menus.Select(m => new MenuDto(m.Id, m.MenuName, m.MenuCode, m.ParentId, m.Icon, m.Path, m.Description));
            var result = dtos.Where(predicate);
            return ApiResponse<IEnumerable<MenuDto>>.Success(result);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "条件查询多个菜单异常");
            return ApiResponse<IEnumerable<MenuDto>>.Fail($"条件查询多个菜单异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<MenuDto?>> GetDtoByIdAsync(Guid id)
    {
        var menu = await _menuRepository.GetByIdAsync(id);
        if (menu == null)
            return ApiResponse<MenuDto?>.Fail("菜单不存在");
        var dto = new MenuDto(menu.Id, menu.MenuName, menu.MenuCode, menu.ParentId, menu.Icon, menu.Path, menu.Description);
        return ApiResponse<MenuDto?>.Success(dto);
    }

    /// <summary>
    /// 为菜单分配角色（菜单-角色关联）
    /// </summary>
    /// <param name="menuId">菜单ID</param>
    /// <param name="roleId">角色ID</param>
    /// <returns>分配结果</returns>
    public async Task<ApiResponse<bool>> AssignRoleAsync(Guid menuId, Guid roleId)
    {
        try
        {
            Log.Information("开始为菜单分配角色，MenuId={MenuId}, RoleId={RoleId}", menuId, roleId);
            
            // 检查菜单是否存在
            var menu = await _menuRepository.GetByIdAsync(menuId);
            if (menu == null)
            {
                return ApiResponse<bool>.Fail("菜单不存在");
            }

            // 注意：这里需要实现角色-菜单关联表的逻辑
            Log.Warning("菜单角色关联功能需要实现角色菜单关联表");
            return ApiResponse<bool>.Success(true, "分配角色功能需要实现角色菜单关联表");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "为菜单分配角色异常");
            return ApiResponse<bool>.Fail($"为菜单分配角色异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 移除菜单的角色关联
    /// </summary>
    /// <param name="menuId">菜单ID</param>
    /// <param name="roleId">角色ID</param>
    /// <returns>移除结果</returns>
    public async Task<ApiResponse<bool>> RemoveRoleAsync(Guid menuId, Guid roleId)
    {
        try
        {
            Log.Information("开始移除菜单的角色关联，MenuId={MenuId}, RoleId={RoleId}", menuId, roleId);
            
            var menu = await _menuRepository.GetByIdAsync(menuId);
            if (menu == null)
            {
                return ApiResponse<bool>.Fail("菜单不存在");
            }

            Log.Warning("菜单角色关联功能需要实现角色菜单关联表");
            return ApiResponse<bool>.Success(true, "移除角色功能需要实现角色菜单关联表");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "移除菜单角色关联异常");
            return ApiResponse<bool>.Fail($"移除菜单角色关联异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 设置菜单父级（支持并发安全）
    /// </summary>
    /// <param name="menuId">菜单ID</param>
    /// <param name="parentId">父菜单ID，null表示设为根菜单</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>设置结果</returns>
    public async Task<ApiResponse<bool>> SetParentAsync(Guid menuId, Guid? parentId, CancellationToken cancellationToken = default)
    {
        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            Log.Information("开始设置菜单父级，MenuId={MenuId}, ParentId={ParentId}", menuId, parentId);
            
            var menu = await _menuRepository.GetByIdAsync(menuId);
            if (menu == null)
            {
                return ApiResponse<bool>.Fail("菜单不存在");
            }

            // 如果设置了父菜单，需要验证父菜单是否存在
            if (parentId.HasValue)
            {
                var parentMenu = await _menuRepository.GetByIdAsync(parentId.Value);
                if (parentMenu == null)
                {
                    return ApiResponse<bool>.Fail("父菜单不存在");
                }

                // 防止循环引用：检查父菜单不能是当前菜单的子菜单
                if (parentId == menuId)
                {
                    return ApiResponse<bool>.Fail("不能将菜单设置为自己的父菜单");
                }

                // 使用实体的SetParent方法
                menu.SetParent(parentMenu);
            }
            else
            {
                // 清除父菜单
                menu.ClearParent();
            }

            await _menuRepository.UpdateAsync(menu);
            
            // 更新缓存
            AddToCache(menu);
            
            Log.Information("菜单父级设置成功");
            return ApiResponse<bool>.Success(true, "菜单父级设置成功");
        }
        catch (OperationCanceledException)
        {
            Log.Warning("设置菜单父级操作被取消，MenuId={MenuId}", menuId);
            return ApiResponse<bool>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "设置菜单父级异常");
            return ApiResponse<bool>.Fail($"设置菜单父级异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 设置菜单启用状态（支持并发安全）
    /// </summary>
    /// <param name="menuId">菜单ID</param>
    /// <param name="enabled">是否启用</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>设置结果</returns>
    public async Task<ApiResponse<bool>> SetEnabledAsync(Guid menuId, bool enabled, CancellationToken cancellationToken = default)
    {
        await _operationSemaphore.WaitAsync(cancellationToken);
        try
        {
            Log.Information("开始设置菜单启用状态，MenuId={MenuId}, Enabled={Enabled}", menuId, enabled);
            
            var menu = await _menuRepository.GetByIdAsync(menuId);
            if (menu == null)
            {
                return ApiResponse<bool>.Fail("菜单不存在");
            }

            // 更新菜单启用状态
            menu.IsActive = enabled;
            await _menuRepository.UpdateAsync(menu);
            
            // 更新缓存
            AddToCache(menu);
            
            Log.Information("菜单启用状态设置成功");
            return ApiResponse<bool>.Success(true, "菜单启用状态设置成功");
        }
        catch (OperationCanceledException)
        {
            Log.Warning("设置菜单启用状态操作被取消，MenuId={MenuId}", menuId);
            return ApiResponse<bool>.Fail("操作被取消");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "设置菜单启用状态异常");
            return ApiResponse<bool>.Fail($"设置菜单启用状态异常: {ex.Message}");
        }
        finally
        {
            _operationSemaphore.Release();
        }
    }

    /// <summary>
    /// 设置菜单父级（接口兼容性版本）
    /// </summary>
    public async Task<ApiResponse<bool>> SetParentAsync(Guid menuId, Guid? parentId)
    {
        return await SetParentAsync(menuId, parentId, CancellationToken.None);
    }

    /// <summary>
    /// 设置菜单启用状态（接口兼容性版本）
    /// </summary>
    public async Task<ApiResponse<bool>> SetEnabledAsync(Guid menuId, bool enabled)
    {
        return await SetEnabledAsync(menuId, enabled, CancellationToken.None);
    }

    #region 资源释放

    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// 释放资源
    /// </summary>
    /// <param name="disposing">是否正在释放</param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            _operationSemaphore?.Dispose();
            _cacheLock?.Dispose();
            ClearCache();
        }
    }

    #endregion
}
